...loading
2024-11-19
이제껏 막연히 여겨왔던 상태관리에 대해서 알아보려한다. 상태관리라는 말은 많이 들어보았고, 여러 상태들을 예민하게 관리해야하는 UI 또한 개발해본 경험은 있었다. 하지만 왜 상태관리가 필요한지, 개발 중인 어플리케이션에서 어떻게 하면 효율적으로 상태를 관리할지에 대해서는 깊게 생각해본 적은 없던 것 같다. 따라서 이번 포스팅에서는 상태 관리에 대해 알아보려 한다. 프론트엔드 개발에서 상태란 무엇이고, 이것이 왜 관리 대상인지, 그리고 어떻게 발전되었는지에 대해 알아보고자 한다.
프론트엔드 개발에서 상태(state)란 무엇일까. 상태(state)란 어플리케이션에서의 유의미한 값을 의미하며, 어플리케이션 사용 과정 중에 지속적으로 변화할 수 있는 값을 의미한다. 다시 말해 어플리케이션 사용 중 사용자와 상호 작용이 가능한 요소들의 현재 값이라 볼 수 있다. 예컨데, 현재 이 블로그에서 적용되는 라이트/다크 모드 또한 상태이며 검색창에서 사용자가 입력하는 타이핑 값 등도 상태다.
한편 현대의 웹은 사용자에게 데이터를 단순히 정적으로 보여주는 것을 넘어섰고, 사용자와 다양한 상호작용이 가능하도록 발전됐다. 따라서 그만큼 하나의 웹 어플리케이션이 내포하게 되는 상태들의 수 또한 많아졌다. 문제는 이러한 상태들이 많아지며 개발과 관리가 점점 복잡해진 것이다.
페이스북의 FLUX패턴이 등장하기 전 기존의 프론트엔드의 웹개발은 MVC패턴을 사용했다. MVC패턴이란 Model, View, Controller의 약자로 Model에 상태를 저장하고 View가 이에 따라 화면을 스케치하게 된다. 그리고 사용자가 View에서 특정 상태를 변화시킨다면 이 동작은 Controller로 전달되어 Model을 변화시키게 된다. 이러한 프로세스를 통해 상태가 변경된다. 하지만 MVC패턴은 상태 데이터가 많은 대규모 어플리케이션의 경우 문제가 발생할 수 있다.
MVC 패턴을 사용한 어플리케이션은 상태(데이터)가 많아질수록 이를 관리하는 Model이 증가하게 된다. 또한 사용자와의 상호작용으로 인해 특정 View의 변동이 발생하면 이는 곧 다른 Model의 변동에 영향을 주게 되며, 이는 또 다른 View 변동의 연쇄작용으로 이어질 수 있다. 이는 관리해야할 상태의 개수가 많아질수록 문제를 심화시킬 수 있다. 특정 상태의 변동과 리렌더링을 추적하는 것이 매우 복잡해지기 때문이다. 즉, Model과 View들의 복잡한 의존성으로 인해 유지보수의 악영향으로 이어지는 것이다.
페이스북은 Model과 View들의 의존성으로 인해 데이터의 흐름이 복잡해지는 MVC패턴의 문제를 지적했다. 그리고 이를 해결하기 위해서 FLUX패턴을 발표한다.
위의 그림이 FLUX패턴의 구조이다. 사용자를 통해 Action이 들어오면 Dispatcher는 Store에 해당 액션을 전달한다. 이 Store에는 어플리케이션의 모든 상태들과 이를 변경하는 메서드들이 관리된다. Store 내부의 상태들이 변경된다면 Store는 변경사항을 View로 전달하게 된다. 또한 View 단에서 사용자와의 상호작용으로 인하여 Action이 발생하면 이는 다시 Dispatcher에 전달되어 동일 과정이 반복된다.
FLUX패턴의 장점은 어플리케이션의 상태데이터가 많아 복잡해진다고 하더라도 데이터 흐름의 단순함을 보장한다는 것이다. 페이스북은 이러한 패턴을 적용하여 상태의 변화와 영향을 쉽게 추적하고 관리할 수 있도록 하였다.
이처럼 상태관리의 필요성이 대두되며 Flux패턴이 등장했고, 이어서 해당 패턴을 사용한 상태관리 라이브러리 Redux가 등장했다. 리액트의 useState, useReducer, Context API 등이 등장하기 전에는 React와 Redux를 함께 사용하는 것이 표준처럼 되어왔다. 그러나 리액트 16.8에서 등장한 훅과 함수형 컴포넌트 패러다임이 적용되며, 이를 채택하여 리액트 전용 상태관리를 도와주고 라이브러리인 Recoil, Jotai 등이 등장하게 되었다. 또한 Redux와 유사하지만 보다 직관적으로 리액트 상태관리를 도와주는 Zustand 등의 라이브러리도 등장한다. 이처럼 현재는 상태관리를 하기 위한 많은 선택지들이 있다. 개발하고자 하는 어플리케이션의 특성과 개발자의 판단으로 적절한 라이브러리를 채택하는 것이 중요하다고 생각한다.
웹 어플리케이션의 발전으로 증가하는 상태들의 관리는 필수적인 요소가 되었다. 기존 UI 컴포넌트 개발을 위한 리액트 또한 현재는 useState, useReducer, ContextAPI의 상태 관리 기능을 지원하고 있다. 하지만 기본 기능 외에도 많은 라이브러리들이 존재한다. 그 이유는 전역 상태를 관리할 필요성이 있기 때문이다.
어플리케이션을 개발하다보면 특정 상태를 여러 컴포넌트들에서 사용해야할 경우가 발생한다. 이를 리액트의 useState를 통해 구현해야한다면 상위 컴포넌트에서 상태를 정의한 후 하위 컴포넌트들에게 전달해야만 한다. 컴포넌트들의 깊이가 길어질수록 해당 상태를 연쇄적으로 전달해야하는 Props Drilling이 발생하게 된다. 그리고 이는 제품의 관리 측면에서 복잡성을 증가시킨다. 만약 상태를 정의한 후 필요한 컴포넌트에서만 사용할 수 있다면, 제품의 관리 및 성능의 측면에서 도움을 줄 수 있다. 따라서 이에 도움을 줄 수 있는 라이브러리를 선택할 수 있는 것이다.
이상 웹 프론트엔드 개발에서 상태란 무엇인지, 그리고 상태 관리가 왜 필요하고 어떻게 발전해왔는지를 알아보았다. 이제까지 상태관리에 대해 조금은 막연하게 생각하고 있었다. 상태 관리 라이브러리를 채택하는 기준도 깊게 고민을 하기 보다는 러닝커브와 인기만 고려하였다. 이번 정리를 계기로 더욱 확고하고 합리적인 기준으로 도구를 사용하고자 한다.
Comments